package com.thunder.reader.transaction;

import java.util.ArrayList;

import android.app.Service;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.util.Log;

public class TransactionService extends Service implements Observer {
    private static final String TAG = "TransactionService";
    private Looper mServiceLooper;
    private Handler mServiceHandler;
    //TODO: use a better structure to hold transactions being processed
    private ArrayList<Transaction> mProcessingQueue;
    
    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread(TransactionService.class.getName(), Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
        mProcessingQueue = new ArrayList<Transaction>();
    }
    
    @Override
    public int onStartCommand(Intent intent, int flag, int startId) {
        if (intent == null) {
            return START_NOT_STICKY;
        }
        if (intent.getData() != null) {
            final Message msg = new Message();
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
        return START_NOT_STICKY;
    }
    
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private class ServiceHandler extends Handler {
        ServiceHandler(Looper looper) {
            super(looper);
        }
        
        @Override
        public void handleMessage(Message msg) {
            final Intent intent = (Intent) msg.obj;
            final Uri uri = intent.getData();
            final int type = intent.getIntExtra(Transaction.EXTRA_TRANSACTION_TYPE, Transaction.TRANSACTION_TYPE_UPDATE_ALL);
            final TransactionData data = new TransactionData(uri, type);
            Transaction transaction = null;
            switch (type) {
            case Transaction.TRANSACTION_TYPE_UPDATE_ALL:
            case Transaction.TRANSACTION_TYPE_UPDATE_FEED:
            case Transaction.TRANSACTION_TYPE_UPDATE_GROUP: {
                transaction = new UpdateFeedTransaction(getApplication(), data);
                break;
            }
            default:
                break;
            }
            assert(transaction == null);
            synchronized (mProcessingQueue) {
                // Check the processing transactions, if the transaction is already running, do nothing
                for (Transaction t : mProcessingQueue) {
                    if (t.equals(transaction)) {
                        return;
                    }
                }
                mProcessingQueue.add(transaction);
            }
            transaction.registerObserver(TransactionService.this);
            transaction.process();
        }
    }

    public void update(TransactionData data) {
        // Transaction finished processing the uri(task), remove it from queue.
    }
}